using UnityEngine;
using System.Collections;

[RequireComponent(typeof(InputController))]
public class PlayerController : MonoBehaviour {

	// Components
	private PlayerPhysics playerPhysics;
	[HideInInspector] public Animator activeAnimator;
	public Animator athorAnimator;
	public Animator lilithAnimator;	

	public BoxCollider colliderAthor;
	public BoxCollider colliderLilith;

	public GameObject ghost;
	public GhostController ghostController;
	private GameCamera cam;

	public Transform ghostTarget;

	// Player Handling
	public float gravity = 20;
	public float movementSpeed;
	public float acceleration = 30;
	public float jumpHeight = 12;
	// System

	[HideInInspector]
	private float targetSpeed;
	private Vector2 amountToMove;
	
	//Animator States
	public float st_speed = 0;
	public bool st_dead = false;
	public bool st_damage = false;
	public bool st_grab = false;
	public bool st_jump = false;
	public bool st_attatck = false;
	public bool st_grounded = false;
	public bool st_doubleJump = false;

	//PLAYERS
	public enum CHARS{
		ATHOR,
		LILITH
	}

	public float horizontal;
	public float vertical;
	public CHARS activeCharacter = CHARS.ATHOR;
	
	public float MAX_HEALTH = 100;
	[HideInInspector] 
	public float health;

	public Transform movableObject;

	//Athor
	public GameObject athor;
	public float athorMovementSpeed;
	public Transform axeOrigin;
	public Transform throwingAxe;
	private float axeDirection;

	//Lilith
	public GameObject lilith;
	public float lilithMovementSpeed;

	float dir;

	public bool activeMovableObject;

	void Start () {
		playerPhysics = GetComponent<PlayerPhysics>();

		cam = GetComponent<GameCamera>();
		SpawnGhost();

		health = MAX_HEALTH;
		movementSpeed = athorMovementSpeed;


		if (activeCharacter == CHARS.ATHOR) {
			colliderLilith.enabled = false;
			colliderAthor.enabled = true;
			athor.SetActive(true);
			lilith.SetActive(false);
			movementSpeed = athorMovementSpeed;
			activeAnimator = athorAnimator;
		} else {
			colliderLilith.enabled = true;
			colliderAthor.enabled = false;
			athor.SetActive(false);
			lilith.SetActive(true);
			movementSpeed = lilithMovementSpeed;
			activeAnimator = lilithAnimator;
		}
		ghostController.switchGhost(activeCharacter);

		activeAnimator.SetLayerWeight(1,1);
	}
	
	void Update () {
	}

	void LateUpdate() {
		updateValues ();
	}

	public void updateValues () {



		activeAnimator.SetFloat ("deltaY", playerPhysics.deltaY);

		// Reset acceleration upon collision
		if (playerPhysics.movementStopped) {
			targetSpeed = 0;
		} else {
			// Set animator parameters
			targetSpeed = horizontal * movementSpeed;
		}

		st_speed = IncrementTowards (st_speed, targetSpeed, acceleration);

		// Face Direction & Shot Direction
		float moveDir = horizontal;
		if (moveDir !=0) {
			transform.eulerAngles = (moveDir>0)?Vector3.up * 180:Vector3.zero;
			axeDirection = (moveDir>0) ? 1 : -1;
		}

		// If player is touching the ground
		if (st_grounded) {
			amountToMove.y = 0;
			activeAnimator.SetBool ("grounded", true);
			activeAnimator.SetBool("jump",false);
			st_jump = false;
			st_doubleJump = false;
			if (activeCharacter == CHARS.ATHOR)
				activeAnimator.SetBool("doubleJump",false);	
		}else{
			activeAnimator.SetBool("grounded", false);
		}

		activeAnimator.SetFloat("speed",st_speed);

		// Set amount to move
		amountToMove.x = st_speed;
		amountToMove.y -= gravity * Time.deltaTime;
		playerPhysics.Move(amountToMove * Time.deltaTime);




		//---------

		if(amountToMove.x>0){
			dir=1;
		} else {
			if(amountToMove.x<0) {
				dir=-1;
			}
		}

		for (int i = 0; i<playerPhysics.collisionDivisionsY; i ++) {
			float x = playerPhysics.p.x + (playerPhysics.c.x + playerPhysics.s.x/2) * dir ;
			float y = (playerPhysics.p.y + playerPhysics.c.y - playerPhysics.s.y/2) + playerPhysics.s.y/(playerPhysics.collisionDivisionsY-1) * i;
			playerPhysics.ray = new Ray (new Vector2 (x, y), new Vector2 (dir, 0));
			float distance = 0.2f;//playerPhysics.activeCollider.size.x;;
			Debug.DrawRay(playerPhysics.ray.origin,playerPhysics.ray.direction*(Mathf.Abs(distance)), Color.red, Time.deltaTime, false);
			if (Physics.Raycast (playerPhysics.ray, out playerPhysics.hit, Mathf.Abs (distance), playerPhysics.movableCollisionMask)) {
				Debug.Log ("!!!!!");
				activeMovableObject = true;
				movableObject = playerPhysics.hit.transform;
				break;
			}
			else{
				activeMovableObject = false;
				activeAnimator.SetBool("grab",false);
				st_grab = false;
			}
		}
	}
	

	#region inputs
	public void onJump(){
		if(!st_jump && st_grounded){
			st_jump = true;
			activeAnimator.SetBool("jump",true);	
			amountToMove.y = jumpHeight;
			st_grounded = false;
		} else if(st_jump && !st_doubleJump && (activeCharacter == CHARS.ATHOR)){
			st_doubleJump = true;
			activeAnimator.SetBool("doubleJump",true);
			amountToMove.y = jumpHeight;
			st_grounded = false;
		}
	}


	public void onAttack(){
		AnimatorStateInfo currState = activeAnimator.GetCurrentAnimatorStateInfo(1);
		if (currState.IsName("Attack")) {//.nameHash == Animator.StringToHash("Attack Layer.Attack")) {
			return;
		}

		activeAnimator.SetTrigger("attack");
		switch (activeCharacter) {
			case CHARS.LILITH :
				break;

			case CHARS.ATHOR :
				break;
		}
	}


	public void onContextual(bool pressed) {
		if (pressed) {
			Debug.Log("1");
			if (activeCharacter == CHARS.LILITH) {
				Debug.Log("2");
				if (activeMovableObject) {
					Debug.Log("3");
					activeAnimator.SetBool("grab",true);
					st_grab = true;
				}
			}
		} else {
			activeAnimator.SetBool("grab",false);
			st_grab = false;
		}
	}

	public void switchCharacter(){

		switch (activeCharacter) {
			case CHARS.ATHOR :
				activeCharacter = CHARS.LILITH;
				activeAnimator = lilithAnimator;
				athor.SetActive(false);
				lilith.SetActive(true);
				movementSpeed = lilithMovementSpeed;
				colliderLilith.enabled = true;
				colliderAthor.enabled = false;
				break;

			case CHARS.LILITH :
				activeCharacter = CHARS.ATHOR;
				activeAnimator = athorAnimator;
				athor.SetActive(true);
				lilith.SetActive(false);
				movementSpeed = athorMovementSpeed;
				colliderAthor.enabled = true;
				colliderLilith.enabled = false;
				break;
		}
		ghostController.switchGhost(activeCharacter);



	}

	#endregion

	// Increase n towards target by speed
	private float IncrementTowards(float n, float target, float a) {
		if (n == target) {
			return n;	
		} else {
			float dir = Mathf.Sign(target - n); // must n be increased or decreased to get closer to target
			n += a * Time.deltaTime * dir;
			return (dir == Mathf.Sign(target-n))? n: target; // if n has now passed target then return target, otherwise return n
		}
	}

	private void SpawnGhost() {
		ghostController = ((GameObject)Instantiate(ghost,transform.position,Quaternion.identity)).GetComponent<GhostController>();
		ghostController.switchGhost(activeCharacter);
	}




}